package io.renren.ssh;


import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * 树节点对象
 */
public class TreeNode implements Serializable {

    private static final long serialVersionUID = 1L;

    private String id;
    private String parentId;
    private String nodeName;
    private int level = 1;
    private Map<String,Object> attributes;// 属性对象
    private List<TreeNode> children;

    public TreeNode() {
    }

    public TreeNode(String id) {
        this.id = id;
    }

    public TreeNode(String id, String nodeName) {
        this.id = id;
        this.nodeName = nodeName;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    /**
     * 增加一个子节点
     * 
     * @param child 子节点
     */
    public void addNode(TreeNode child) {
        children().add(child);
        child.setParentId(id);
        child.setLevel(level + 1);
    }

    /**
     * 增加多个子节点
     * 
     * @param childs 子节点集合
     */
    public void addNodes(Collection<? extends TreeNode> childs) {
        children().addAll(childs);
        for (TreeNode treeNode : childs) {
            treeNode.setParentId(id);
            treeNode.setLevel(level + 1);
        }
    }

    /**
     * 删除指定索引位置处的子节点
     * 
     * @param index
     * @return 返回删除的子节点,如果索引位置不存在返回null
     */
    public TreeNode removeNode(int index) {
        if (children == null || children.isEmpty()) {
            return null;
        }
        if (index < 0 || index >= children.size()) {
            return null;
        }
        TreeNode removeNode = children.remove(index);
        removeNode.setParentId(null);
        return removeNode;
    }

    /**
     * 删除子节点
     * 
     * @param node 子节点
     * @return 如存在相等子节点删除并返回true,否则返回false
     */
    public boolean removeNode(TreeNode node) {
        if (children == null || children.isEmpty()) {
            return false;
        }
        if (children.remove(node)) {
            node.setParentId(null);
            return true;
        }
        return false;
    }

    /**
     * 返回所有子节点的迭代器
     * 
     * @return 子节点的迭代器
     */
    public Iterator<TreeNode> nodeIterator() {
        return children().iterator();
    }

    /**
     * 返回 所有子节点的不可变列表
     * 
     * @return
     */
    public List<TreeNode> getChildren() {
        return children != null ? Collections.unmodifiableList(children) : null;
    }

    protected List<TreeNode> children() {
        if (children == null) {
            children = new ArrayList<>();
        }
        return children;
    }

    public String getParentId() {
        return parentId;
    }

    public void setParentId(String parentId) {
        this.parentId = parentId;
    }

    /**
     * 是否叶子节点,即是否有子节点
     * 
     * @return
     */
    public boolean isLeaf() {
        return children == null || children.isEmpty();
    }

    public boolean hasChild() {
        return !isLeaf();
    }

    /**
     * 返回 子节点的个数
     * 
     * @return
     */
    public int nodeSize() {
        return children == null ? 0 : children.size();
    }

    public String getNodeName() {
        return nodeName;
    }

    public void setNodeName(String nodeName) {
        this.nodeName = nodeName;
    }

    /*void setParent(TreeNode parent) {
        this.parent = parent;
        setLevel(parent.getLevel() + 1);
    }
    
    void removeParent() {
        this.parent = null;
        level = level > 1 ? level - 1 : 1;
    }
    */
    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    public Map<String,Object> getAttributes() {
        return attributes;
    }

    public void setAttributes(Map<String,Object> attributes) {
        this.attributes = attributes;
    }

    /**
     * 设置属性
     * 
     * @param name
     * @param value
     */
    public void setAttribute(String name, Object value) {
        attributes().put(name, value);
    }

    /**
     * 获取属性值
     * 
     * @param name 属性名
     * @return
     */
    public Object getAttribute(String name) {
        return attributes().get(name);
    }

    /**
     * 返回节点动态属性Map
     * 
     * @return {@code Map<String,Object>}
     */
    public Map<String,Object> attributes() {
        if (attributes == null) {
            attributes = new HashMap<>();
        }
        return attributes;
    }

    /**
     * 用给定的节点集合构建树
     * 
     * @param rootId 根节点id
     * @param nodes 节点集合
     * @return
     */
    public static List<TreeNode> buildTree(String rootId, List<TreeNode> nodes) {
        TreeNode root = new TreeNode(rootId, "root");
        root.setLevel(0);
        final List<TreeNode> nodesCopy = new ArrayList<>(nodes);
        buildTree(root, nodesCopy);
        return root.getChildren();
    }

    /**
     * 用给定的节点集合构建树,构建的树作为根节点的子孙.
     * 
     * @param parent 根节点
     * @param nodes
     */
    public static <T extends TreeNode> void buildTree(TreeNode parent, List<T> nodes) {
        Iterator<T> it = nodes.iterator();
        TreeNode node = null;
        while (it.hasNext()) {
            node = it.next();
            if (parent.getId()
                    .equals(node.getParentId())) {
                parent.addNode(node);
                it.remove();// 从集合里删除,减少下次迭代时遍历数量
            }
        }
        if (parent.hasChild()) {
            parent.nodeIterator()
                    .forEachRemaining((n) -> buildTree(n, nodes));
        }
    }

    /**
     * 把给定类型的集合转为树结构
     * 
     * @param <T>
     * @param parent
     * @param nodes
     * @param fun T转TreeNode的方法
     */
    public static <T> void buildTree(TreeNode parent, List<T> nodes, Function<T,TreeNode> fun) {
        Iterator<T> it = nodes.iterator();
        TreeNode node = null;
        while (it.hasNext()) {
            node = fun.apply(it.next());
            if (parent.getId()
                    .equals(node.getParentId())) {
                parent.addNode(node);
                it.remove();// 从集合里删除,减少下次迭代时遍历数量
            }
        }
        if (parent.hasChild()) {
            parent.nodeIterator()
                    .forEachRemaining((n) -> buildTree(n, nodes, fun));
        }
    }

    /* public static void main(String[] args) {
        TreeNode node1 = new TreeNode("1", "node1");
        TreeNode node2 = new TreeNode("2", "node2");
        TreeNode node3 = new TreeNode("3", "node3");
        TreeNode node33 = new TreeNode("33", "node33");
    
        node1.setParentId("0");
        node2.setParentId("0");
        node3.setParentId("0");
        node33.setParentId("3");
    
        List<TreeNode> nodes = TreeNode.buildTree("0", Arrays.asList(node1, node2, node3, node33));
        System.out.println(JsonHelper.toJson(nodes));
    }*/
}